package demo.java.lang;

import demo.vo.UserVO;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class ObjectDemo {

    static Logger logger = LoggerFactory.getLogger(ObjectDemo.class);

    /**
     * 数组的hashCode不一致，且不同。应该是默认走了Object的方法
     */
    @Test
    public void testEquals() {
        logger.info("---------------数组对比--------------");
        String[] array1 = {"a", "b"};
        String[] array2 = {"a", "b"};
        logger.info("array1.hashCode = {}, array2.hashCode = {}", array1.hashCode(), array2.hashCode());
        logger.info("array1.equals(array2) = {}", array1.equals(array2));
        logger.info("--------------Object对比---------------");
        Object object1 = new Object();
        Object object2 = new Object();
        logger.info("object1.hashCode = {}, object2.hashCode = {}", object1.hashCode(), object2.hashCode());
        logger.info("object1.equals(object2) ={}", object1.equals(object2));
    }

    /**
     * <h1>浅拷贝</h1>：创建一个新对象，然后将当前对象的非静态字段复制到该对象，如果字段类型是值类型（基本类型）的，那么对该字段进行复制；
     * 如果字段是引用类型的，则只复制该字段的引用而不复制引用指向的对象。 此时新对象里面的引用类型字段相当于是原始对象里面引用类型字段的一个副本，
     * 原始对象与新对象里面的引用字段指向的是同一个对象。
     * <h1>深拷贝</h1>了解了浅拷贝，那么深拷贝是什么也就很清楚了。即将引用类型的属性内容也拷贝一份新的。 实现深拷贝我这里收集到两种方式：
     * <li>第一种是给需要拷贝的引用类型也实现Cloneable接口并覆写clone方法；
     * <li>第二种则是利用序列化。
     *
     * @throws IOException
     * @throws ClassNotFoundException
     */
    @Test
    public void testClone() throws ClassNotFoundException, IOException {
        UserVO user1 = new UserVO();
        user1.setId(0);
        user1.setAddress("上海");
        user1.setAge(30);
        user1.setName("东升");
        UserVO user2 = (UserVO) user1.deepClone();
        System.out.println(user1);
        System.out.println(user2);
    }

    /**
     * 哈希算法将任意长度的二进制值映射为固定长度的较小二进制值，这个小的二进制值称为哈希值。
     * 哈希值是一段数据唯一且极其紧凑的数值表示形式。
     * 如果散列一段明文而且哪怕只更改该段落的一个字母，随后的哈希都将产生不同的值。
     * 要找到散列为同一个值的两个不同的输入，在计算上来说基本上是不可能的。
     */
    @Test
    public void demoHashCode() {
        Object object = new Object();
        int hashCode = object.hashCode();
        System.out.println(hashCode);
        System.out.println(object.hashCode());
        System.out.println("hello world".hashCode());
        System.out.println( -2 % 2);
        System.out.println( -3 % 2);
    }

    @Test
    public void testObjectSize() throws InterruptedException {
        // 加到集合中，使垃圾无法回收
        List<EmptyObject> emptys = new ArrayList<>();
        for (int i = 0; i < 100; i++) {
            emptys.add(new EmptyObject());
        }
        logger.info("打开jvisualvm,查看EmptyObject的大小为16字节");
        Thread.sleep(60 * 1000);
    }

}

class EmptyObject {
}
